﻿using AutoMapper;
using ManagementApi.Authorizers;
using ManagementApi.Models;
using ManagementApi.Models.Device;
using ManagementApi.Models.System.ProjectCheckinDeviceCommandLog;
using ManagementApi.Mvc;
using ManagementApi.Mvc.ApplicationContexts;
using ManagementApi.Mvc.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Modules.Device;
using Modules.Device.Entitys;
using PmSoft;
using PmSoft.Utilities;
using static Modules.Device.CheckInDeviceConstants;

namespace ManagementApi.Controllers.AdminPannel
{
    /// <summary>
    /// 项目考勤机设备管理
    /// </summary>
    [Route("/api/v1/sysuser/checkindevice")]
    [ApiController]
    [Authorize(Roles = "SysUser")]
    public class CheckInDeviceController : ControllerBase
    {
        private readonly CheckinDeviceService checkinDeviceService;
        private readonly CheckinDeviceCommandService projectCheckinDeviceCommandService;
        private readonly ManagementApplicationContext applicationContext;
        private readonly IMapper mapper;
        private readonly ProjectOwnAuthorizer ownAuthorizer;
        //private readonly SzDeviceService szDeviceService;

        /// <summary>
        /// </summary>
        /// <param name="applicationContext"></param>
        /// <param name="mapper"></param>
        /// <param name="checkinDeviceService"></param>
        /// <param name="projectCheckinDeviceCommandService"></param>
        public CheckInDeviceController(ManagementApplicationContext applicationContext
            , IMapper mapper
            , CheckinDeviceService checkinDeviceService
            , CheckinDeviceCommandService projectCheckinDeviceCommandService
            , ProjectOwnAuthorizer ownAuthorizer
            //, SzDeviceService szDeviceService
            )
        {
            this.applicationContext = applicationContext;
            this.mapper = mapper;
            this.checkinDeviceService = checkinDeviceService;
            this.projectCheckinDeviceCommandService = projectCheckinDeviceCommandService;
            this.ownAuthorizer = ownAuthorizer;
            //this.szDeviceService = szDeviceService;
        }

        /// <summary>
        /// 获取考勤机信息列表(分页)
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="pageNum">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        [HttpGet("page")]
        public ApiResult<PageDto<CheckInDeviceDto>> GetProjectCheckInDevices([FromQuery] CheckInDeviceQuery query, int pageNum = 1, int pageSize = 20)
        {
            var devices = checkinDeviceService.GetProjectCheckinDevices(query, pageNum, pageSize);
            var dtos = devices.AsPageDto(source => { return source.AsDto(applicationContext); });
            return ApiResult<PageDto<CheckInDeviceDto>>.Success(dtos);
        }

        /// <summary>
        /// 创建考勤机信息
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost("create")]
        [PermissionCheck("sys:checkindevice:add")]
        public ApiResult Add([FromBody] CheckInDeviceEditForm form)
        {
            CheckinDevice device = new CheckinDevice();
            mapper.Map(form, device);
            device.CreateTime = DateTime.Now;
            checkinDeviceService.Create(device);
            return ApiResult.Success("创建成功");
        }

        /// <summary>
        /// 考勤机信息表单数据
        /// </summary>
        /// <param name="id">角色ID</param>
        /// <returns></returns>
        [HttpGet("{id}/form")]
        public ApiResult<CheckInDeviceEditForm> GetRole(int id)
        {
            var device = checkinDeviceService.GetProjectCheckinDevice(id);
            if (device == null)
                return ApiResult<CheckInDeviceEditForm>.Failure("考勤机信息数据不存在");
            return ApiResult<CheckInDeviceEditForm>.Success(device.AsForm());
        }

        /// <summary>
        /// 修改考勤机信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="deviceEditForm"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        [PermissionCheck("sys:checkindevice:edit")]
        public ApiResult Update(int id, [FromBody] CheckInDeviceEditForm deviceEditForm)
        {
            var device = checkinDeviceService.GetProjectCheckinDevice(id);
            if (device == null) return ApiResult.Failure("考勤机信息不存在");

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(deviceEditForm.ProjectId);

            #endregion 验证数据权限

            mapper.Map(deviceEditForm, device);
            checkinDeviceService.Update(device);
            return ApiResult.Success("修改成功");
        }

        /// <summary>
        /// 删除考勤机信息
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpDelete("{ids}")]
        [PermissionCheck("sys:checkindevice:delete")]
        public ApiResult Delete(string ids)
        {
            var datas = checkinDeviceService.GetProjectCheckinDevices(ValueUtility.ConvertToList<int>(ids));

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(datas.Select(i => i.ProjectId));

            #endregion 验证数据权限

            checkinDeviceService.Deletes(ValueUtility.ConvertToList<int>(ids));
            return ApiResult.Success("删除成功");
        }

        /// <summary>
        /// 禁用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPut("disable/{id}")]
        [PermissionCheck("sys:checkindevice:disable")]
        public ApiResult DisableDevice(int id)
        {
            var device = checkinDeviceService.GetProjectCheckinDevice(id);
            if (device == null) return ApiResult.Failure("设备信息不存在");

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(device.ProjectId);

            #endregion 验证数据权限

            device.IsDisable = true;
            checkinDeviceService.Update(device);
            return ApiResult.Success("禁用成功");
        }

        /// <summary>
        /// 启用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPut("enable/{id}")]
        [PermissionCheck("sys:checkindevice:enable")]
        public ApiResult EnableDevice(int id)
        {
            var device = checkinDeviceService.GetProjectCheckinDevice(id);
            if (device == null) return ApiResult.Failure("设备信息不存在");

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(device.ProjectId);

            #endregion 验证数据权限

            device.IsDisable = false;
            checkinDeviceService.Update(device);
            return ApiResult.Success("启用成功");
        }

        /// <summary>
        /// 延长时限
        /// </summary>
        /// <param name="id"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        [HttpPut("upenddate/{id}")]
        [PermissionCheck("sys:checkindevice:upenddate")]
        public ApiResult UpdateEndDate(int id, DateTime endDate)
        {
            var device = checkinDeviceService.GetProjectCheckinDevice(id);
            if (device == null) return ApiResult.Failure("设备信息不存在");

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(device.ProjectId);

            #endregion 验证数据权限

            if (endDate <= device.StartDate) return ApiResult.Failure("结束日期不能小于开始日期");
            device.EndDate = endDate;
            checkinDeviceService.Update(device);
            return ApiResult.Success("操作成功");
        }

        /// <summary>
        /// 批量下发命令
        /// </summary>
        /// <param name="ids">设备id</param>
        /// <param name="codes">命令编码</param>
        /// <returns></returns>
        [HttpPost("issuecommand")]
        [PermissionCheck("sys:checkindevice:issuecommand")]
        public async Task<ApiResult> IssueCommand(string ids, string codes)
        {
            //string host = $"{HttpContext.Request.Host.Host}:{HttpContext.Request.Host.Port}";
            if (string.IsNullOrEmpty(ids)) return ApiResult.Failure("设备不能为空");
            if (string.IsNullOrEmpty(codes)) return ApiResult.Failure("请选择要下发的命令");
            var deviceIds = ValueUtility.ConvertToList<int>(ids);
            var commandCodes = ValueUtility.ConvertToList<考勤机命令>(codes);
            IEnumerable<CheckinDevice> devices = checkinDeviceService.GetProjectCheckinDevices(deviceIds);

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(devices.Select(i => i.ProjectId));

            #endregion 验证数据权限

            foreach (var device in devices)
            {
                foreach (var commandType in commandCodes)
                {
                    CheckinDeviceCommand command = new CheckinDeviceCommand()
                    {
                        Name = commandType.GetDescription(),
                        Code = commandType,
                        MessageId = Guid.NewGuid().ToString(),
                        DeviceCode = device.Code,
                        Status = 命令下发状态.待下发,
                        IsAuto = false
                    };
                    projectCheckinDeviceCommandService.Send(command, device);

                }
            }
            return ApiResult.Success("下发成功");
        }

        /// <summary>
        /// 获取考勤机下发记录列表(分页)
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="pageNum">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        [HttpGet("log_page")]
        public ApiResult<PageDto<ProjectCheckinDeviceCommandDto>> GetProjectCheckInDeviceCommands([FromQuery] CheckinDeviceCommandQuery query, int pageNum = 1, int pageSize = 20)
        {
            var devices = projectCheckinDeviceCommandService.GetProjectCheckinDeviceCommands(query, pageNum, pageSize);
            List<int> deviceIds = devices.Select(a => a.Id).ToList();
            var dtos = devices.AsPageDto(source => { return source.AsDto(); });
            return ApiResult<PageDto<ProjectCheckinDeviceCommandDto>>.Success(dtos);
        }
    }
}